home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  6.4 KB  |  285 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: server.c,v 5.3 1992/11/17 06:34:06 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <syslog.h>
  12. #include <fcntl.h>
  13. #include <time.h>
  14.  
  15. #include "fsma.h"
  16. #include "sio.h"
  17.  
  18. #include "access.h"
  19. #include "connection.h"
  20. #include "config.h"
  21. #include "server.h"
  22. #include "state.h"
  23. #include "logoptions.h"
  24.  
  25. #define server_free( serp )         fsm_free( server_allocator, (char *)serp )
  26.  
  27.  
  28. char *inet_ntoa() ;
  29. time_t time() ;
  30.  
  31. void msg() ;
  32. void out_of_memory() ;
  33.  
  34. static fsma_h server_allocator ;
  35.  
  36.  
  37. status_e server_init()
  38. {
  39.     int flags = FSM_RETURN_ERROR ;
  40.  
  41. #ifdef DEBUG
  42.     flags |= FSM_ZERO_FREE ;
  43. #endif
  44.     server_allocator = fsm_create( sizeof( struct server ), 0, flags ) ;
  45.     return( ( server_allocator == NULL ) ? FAILED : OK ) ;
  46. }
  47.  
  48.  
  49.  
  50. /*
  51.  * Allocate a server, initialize it from init_serp, and insert it in stab
  52.  */
  53. struct server *server_alloc( init_serp, stab )
  54.     struct server *init_serp ;
  55.     pset_h stab ;
  56. {
  57.     register struct server *serp ;
  58.     char *func = "server_alloc" ;
  59.  
  60.     serp = SERP( fsm_alloc( server_allocator ) ) ;
  61.     if ( serp == NULL )
  62.     {
  63.         out_of_memory( func ) ;
  64.         return( NULL ) ;
  65.     }
  66.  
  67.     *serp = *init_serp ;
  68.  
  69.     if ( pset_add( stab, serp ) == NULL )
  70.     {
  71.         msg( LOG_CRIT, func, "couldn't insert server in server table" ) ;
  72.         fsm_free( server_allocator, (char *) serp ) ;
  73.         return( NULL ) ;
  74.     }
  75.  
  76.     return( serp ) ;
  77. }
  78.  
  79.  
  80. status_e server_run( sp, cp )
  81.     struct service *sp ;
  82.     connection_s *cp ;
  83. {
  84.     struct server server ;
  85.     struct server *serp ;
  86.     char *func = "server_run" ;
  87.     status_e schedule_retry() ;
  88.     void server_internal() ;
  89.     void log_failure() ;
  90.  
  91.     CLEAR( server ) ;
  92.     SERVER_SERVICE( &server ) = sp ;
  93.     SERVER_CONNECTION( &server ) = cp ;
  94.  
  95.     /*
  96.      * Allocate a server struct only if we will fork a new process
  97.      */
  98.     if ( ! SVC_FORKS( sp ) )
  99.     {
  100.         server_internal( &server ) ;
  101.         return( OK ) ;
  102.     }
  103.  
  104.     serp = server_alloc( &server, ps.rws.servers ) ; 
  105.     if ( serp == NULL )
  106.         return( FAILED ) ;
  107.  
  108.     if ( server_start( serp ) == OK )
  109.     {
  110.         SVC_HOLD( sp ) ;
  111.         return( OK ) ;
  112.     }
  113.  
  114.     /*
  115.      * Fork failed; remove the server from the server table
  116.      */
  117.     pset_remove( ps.rws.servers, serp ) ;
  118.  
  119.     /*
  120.      * Currently, fork failures are the only reason for retrying.
  121.      * There is no retry if we exceed the max allowed number of fork failures
  122.      */
  123.     if ( serp->fork_failures < MAX_FORK_FAILURES && SVC_RETRY( sp ) )
  124.     {
  125.         if ( schedule_retry( serp ) == OK )
  126.             return( OK ) ;
  127.         else
  128.             msg( LOG_ERR, func, "Retry failure for %s service", CONF( sp )->id ) ;
  129.     }
  130.     else
  131.         log_failure( AC_FORK, sp, cp ) ;
  132.  
  133.     server_free( serp ) ;
  134.     return( FAILED ) ;
  135. }
  136.  
  137.  
  138. /*
  139.  * If a service is internal and does not require forking a process:
  140.  *        -     if it accepts connections, we put the accepted connection
  141.  *         in non-blocking mode to avoid a possible block on 
  142.  *         the write(2).
  143.  *        -    the log flags that have to do with the server exiting are 
  144.  *            ignored (i.e. nothing is logged).
  145.  *        -    it can be identified in the log because the server pid is 0.
  146.  */
  147. PRIVATE void server_internal( serp )
  148.     struct server *serp ;
  149. {
  150.     register struct service *sp = SERVER_SERVICE( serp ) ;
  151.     register struct service_config *scp = CONF( sp ) ;
  152.     char *func = "server_internal" ;
  153.     void log_success() ;
  154.  
  155.     serp->pid = 0 ;
  156.     if ( ACCEPTS_CONNECTIONS( scp ) &&
  157.                 fcntl( SERVER_FD( serp ), F_SETFL, FNDELAY ) == -1 )
  158.         msg( LOG_ERR, func, "%s: fcntl F_SETFL failed: %m", scp->id ) ;
  159.     else
  160.     {
  161.         log_success( serp ) ;
  162.         (*sp->builtin->function)( serp ) ;
  163.     }
  164. }
  165.  
  166.  
  167. /*
  168.  * Try to fork a server process
  169.  */
  170. status_e server_start( serp )
  171.     register struct server *serp ;
  172. {
  173.     register struct service *sp = SERVER_SERVICE( serp ) ;
  174.     register struct service_config *scp = CONF( sp ) ;
  175.     char *func = "server_start" ;
  176.     void child_process() ;
  177.     void log_success() ;
  178.  
  179.     serp->log_remote_user = ( M_IS_SET( scp->log_on_success, LO_USERID ) &&
  180.                                                                 ACCEPTS_CONNECTIONS( scp ) ) ;
  181.     serp->pid = fork() ;
  182.  
  183.     switch ( serp->pid )
  184.     {
  185.         case 0:
  186.             ps.rws.env_is_valid = FALSE ;
  187.  
  188.             child_process( serp ) ;
  189.  
  190.             msg( LOG_ERR, func, "child_process returned ???" ) ;
  191.             _exit( 0 ) ;
  192.             /* NOTREACHED */
  193.         
  194.         case -1:
  195.             msg( LOG_ERR, func, "%s: fork failed: %m", scp->id ) ;
  196.             serp->fork_failures++ ;
  197.             return( FAILED ) ;
  198.  
  199.         default:
  200.             (void) time( &serp->start_time ) ;
  201.             SDATA( sp )->running_servers++ ;
  202.  
  203.             /*
  204.              * Log the start of another server (if it is not an interceptor).
  205.              * Determine if the server writes to the log (because in that case
  206.              * we will have to check the log size).
  207.              */
  208.             if ( ! IS_INTERCEPTED( scp ) )
  209.                 log_success( serp ) ;
  210.             else
  211.                 serp->writes_to_log =
  212.                             ( SVC_IS_LOGGING( SERVER_SERVICE( serp ) ) != NULL ) ;
  213.             serp->writes_to_log |= serp->log_remote_user ;
  214.             return( OK ) ;
  215.     }
  216. }
  217.  
  218.  
  219. void server_release( serp )
  220.     struct server *serp ;
  221. {
  222.     struct service *sp = SERVER_SERVICE( serp ) ;
  223.  
  224.     if ( SVC_RELE( sp ) == 0 )
  225.         pset_remove( SERVICES( ps ), sp ) ;
  226.     else if ( IS_SUSPENDED( sp ) )
  227.         svc_resume( sp ) ;
  228.     
  229.     server_free( serp ) ;
  230. }
  231.  
  232.  
  233. /*
  234.  * This function is invoked on server exit if the service has installed it
  235.  *
  236.  * NOTE: In case of reconfiguration between server fork and exit, the
  237.  *            service attributes checked in this function may change.
  238.  */
  239. void server_postmortem( serp )
  240.    register struct server *serp ;
  241. {
  242.     struct service *sp = SERVER_SERVICE( serp ) ;
  243.     char *func = "server_postmortem" ;
  244.    register struct service_config *scp = CONF( sp ) ;
  245.    void log_exit() ;
  246.  
  247.     if ( SVC_IS_LOGGING( sp ) )
  248.     {
  249.         if ( serp->writes_to_log )
  250.         {
  251.             if ( debug.on )
  252.                 msg( LOG_DEBUG, func,
  253.                                 "Checking log size of %s service", CONF( sp )->id ) ;
  254.             xlog_control( SDATA( sp )->log_handle, XLOG_SIZECHECK ) ;
  255.         }
  256.  
  257.         if ( M_IS_SET( scp->log_on_success, LO_DURATION ) ||
  258.                      M_IS_SET( scp->log_on_success, LO_EXIT ) )
  259.             log_exit( serp ) ;
  260.     }
  261.  
  262.     conn_free( SERVER_CONNECTION( serp ) ) ;
  263. }
  264.  
  265.  
  266.  
  267. void server_dump( serp, fd )
  268.    register struct server *serp ;
  269.    int fd ;
  270. {
  271.    Sprint( fd, "pid = %d\n", serp->pid ) ;
  272.    Sprint( fd, "start_time = %s", ctime( &serp->start_time ) ) ;
  273.    Sprint( fd, "sp = %p (service=%s)\n", SERVER_SERVICE( serp ),
  274.                                                 CONF( SERVER_SERVICE( serp ) )->id ) ;
  275.     Sprint( fd, "Connection info:\n" ) ;
  276.     conn_dump( SERVER_CONNECTION( serp ), fd ) ;
  277.    Sprint( fd, "fork_failures = %d\n", serp->fork_failures ) ;
  278.    Sprint( fd,
  279.                 "log_remote_user = %s\n", serp->log_remote_user ? "YES" : "NO" ) ;
  280.    Sprint( fd, "writes_to_log = %s\n", serp->writes_to_log ? "YES" : "NO" ) ;
  281.    Sputchar( fd, '\n' ) ;
  282. }
  283.  
  284.  
  285.